ark-ec
defines traits and algorithms for working with different kinds of additive groups, with a focus on groups arising from elliptic curves. It further provides concrete instantiations of these traits for various elliptic curve models, including popular families of pairing-friendly curves such as the BLS12 family of curves.
Implementations of particular curves using these curve models can be found in arkworks-rs/curves
.
Usage
The Group
trait
Many cryptographic protocols use as core building-blocks prime-order groups. The PrimeGroup
trait is an abstraction that represents elements of such abelian prime-order groups. It provides methods for performing common operations on group elements:
use ;
use ;
// We'll use the BLS12-381 G1 curve for this example.
// This group has a prime order `r`, and is associated with a prime field `Fr`.
use ;
use ;
let mut rng = test_rng;
// Let's sample uniformly random group elements:
let a = rand;
let b = rand;
// We can add elements, ...
let c = a + b;
// ... subtract them, ...
let d = a - b;
// ... and double them.
assert_eq!;
// We can also negate elements, ...
let e = -a;
// ... and check that negation satisfies the basic group law
assert_eq!;
// We can also multiply group elements by elements of the corresponding scalar field
// (an act known as *scalar multiplication*)
let scalar = rand;
let e = c.mul;
let f = e.mul;
assert_eq!;
Scalar multiplication
While the PrimeGroup
trait already produces scalar multiplication routines, in many cases one can take advantage of
the group structure to perform scalar multiplication more efficiently. To allow such specialization, ark-ec
provides
the ScalarMul
and VariableBaseMSM
traits. The latter trait computes an "inner product" between a vector of scalars s
and a vector of group elements g
. That is, it computes s.iter().zip(g).map(|(s, g)| g * s).sum()
.
use ;
use ;
// We'll use the BLS12-381 G1 curve for this example.
// This group has a prime order `r`, and is associated with a prime field `Fr`.
use ;
use ;
let mut rng = test_rng;
// Let's sample uniformly random group elements:
let a = rand;
let b = rand;
let s1 = rand;
let s2 = rand;
// Note that we're using the `GAffine` type here, as opposed to `G`.
// This is because MSMs are more efficient when the group elements are in affine form. (See below for why.)
//
// The `VariableBaseMSM` trait allows specializing the input group element representation to allow
// for more efficient implementations.
let r = msm.unwrap;
assert_eq!;
Elliptic curve groups
There are two traits that are important when working with elliptic curves
over finite fields: [CurveGroup
], and [AffineRepr
]. Both traits
represent elements of the same curve, but provide different underlying representations.
In particular, the [CurveGroup
] representation of a curve point is generally
more efficient for arithmetic, but does not provide a unique representative
for a curve point. An [AffineRepr
] representation, on the other hand, is unique,
but is slower for most arithmetic operations. Let's explore how and when to use
these:
use ;
use ;
use ;
use ;
let mut rng = test_rng;
// Let's generate an elliptic curve group element in the `CurveGroup` representation
let a = rand;
// We can convert it the `AffineRepr` representation...
let a_aff = a.into_affine;
// ... and check that the two representations are equal.
assert_eq!;
// We can also convert back to the `CurveGroup` representation:
assert_eq!;
// As a general rule, most group operations are slower when elements
// are represented as `AffineRepr`. However, adding an `AffineRepr`
// point to a `CurveGroup` one is usually slightly more efficient than
// adding two `CurveGroup` points.
let d = a + a_aff;
assert_eq!;
// This efficiency also translates into more efficient scalar multiplication routines.
let scalar = rand;
let mul_result = a_aff * scalar;
assert_eq!;
// Finally, while not recommended, users can directly construct group elements
// from the x and y coordinates of the curve points. This is useful when implementing algorithms
// like hash-to-curve.
let a_x = a_aff.x;
let a_y = a_aff.y;
let is_at_infinity = a_aff.is_zero;
// This check ensures that `new_a` is indeed in the curve group, and in particular
// is within the prime-order group.
let new_a = new;
assert_eq!;
assert!;
assert!;
Besides the foregoing abstract interfaces for elliptic curve groups, ark-ec
also provides
the following concrete instantiations of common elliptic curve models:
- Short Weierstrass curves. The
AffineRepr
in this case is in typical Short Weierstrass point representation, and theCurveGroup
is using points in Jacobian Coordinates. - Twisted Edwards curves. The
AffineRepr
in this case is in standard Twisted Edwards curve representation, whereas theCurveGroup
uses points in Extended Twisted Edwards Coordinates.
Pairings
Pairing
is a trait that defines the interface for a pairing-friendly elliptic curve. Besides the general interface, we provide concrete instantiations of popular pairing-friendly families of curves, such as the Barreto-Lynn-Scott and Barreto-Naehrig families.
use ;
use Field;
use UniformRand;
use ;
use Fr as ScalarField;
// The pairing engine is parameterized by the scalar field of the curve.
let mut rng = test_rng;
let s = rand;
let a = G1 rand;
let b = G2 rand;
// We can compute the pairing of two points on the curve, either monolithically...
let e1 = pairing;
// ... or in two steps. First, we compute the Miller loop...
let ml_result = miller_loop;
// ... and then the final exponentiation.
let e2 = final_exponentiation.unwrap;
assert_eq!;
Hash-to-group
ark-ec
also provides traits for hashing to elliptic curve groups. The HashToCurve
trait allows users to hash arbitrary byte strings to elliptic curve group elements, and allows using different hashing strategies.